package Negocio;

import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.LazyToOne;
import org.hibernate.annotations.LazyToOneOption;

import Interfaz.EnvioDTO;
@Entity
@Table(name="envios")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
	    name="tipo",
	    discriminatorType=DiscriminatorType.STRING
	)
public abstract class Envio {
	@Id
	@Column(name="envio_id")
	@GeneratedValue(strategy = GenerationType.AUTO)
	protected int envioId;
 
	@ManyToOne
	@JoinColumn(name = "cliente_id")
	protected Cliente cliente;
	
	@OneToOne
	@JoinColumn(name = "deposito_id")
	@LazyToOne(LazyToOneOption.FALSE)
	protected Deposito deposito;
	
//	@ManyToOne
//	@JoinColumn(name = "envio_por_destino_id")
//	protected EnviosXDestino envioDestino;
	
	@OneToOne(cascade = CascadeType.ALL)
	protected Carga carga;
	@Column(name="fecha_recepcion")
	protected Date fechaRecepcion; // dia y hora que se recepciona el pedido en la sucursal
	@Column(name="fecha_entrega_comprometida")
	protected Date fechaEntregaComprometida; // dia y hora en la que se compromete la entrega del paquete.
	@Column(name="fecha_limite_de_despacho")
	protected Date fechaLimiteDeDespacho; // ultimo dia y hora en que se puede enviar un paquete, sin incurrir en retrasos.
	@Column(name="fecha_entrega_real")
	protected Date fechaEntregaReal; // fecha en la cual van a retirar el envio en la sucursal de destino
	@Column(name="precio")
	protected Float precio;
	// se obtiene de la ruta al momento de la creacion del envio.
	@Column(name="en_destino")
	protected boolean enDestino;//una vez que el envio se encuentra en destino puede marcarse como entregado
	protected boolean entregado;
	@OneToMany(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
	@JoinColumn(name = "envio_id")
	protected List<Destinatario> destinatarios;
	@Column(name = "en_viaje")
	boolean enViaje;
	
	@Transient
	protected List<ContratoConTerceros> contratosConTerceros;
	@Transient
	EnvioDTO dto;
	
	public Envio() {
		
	}
	
	private boolean existeContratoConTercero (String proveedor) throws Exception {
			return false;
	}
	
	//agregar mas parametros a este metodo
	public void agregarContratoConTercero (String proveedor) throws Exception {
		
		if (!existeContratoConTercero (proveedor)){
			ContratoConTerceros c = new ContratoConTerceros();
			contratosConTerceros.add(c);
		}
		else
			throw (new Exception("Ya existe destinatario con ese dni"));
		
	}
	
	public void agregarDestinatario (String nombre, String apellido, String dni) throws Exception {
		if (!existeDestinatario (dni)){
			Destinatario d = new Destinatario ( nombre,  apellido,  dni);
			destinatarios.add(d);
		}
		else
			throw (new Exception("Ya existe destinatario con ese dni"));
		
	}
	
	private boolean existeDestinatario (String dni) throws Exception {
		for (Destinatario d : destinatarios) {
			if (dni.compareTo(d.getDni())==0)
				return true;			
		}
		return false;
	}

	public int getId() {
		return envioId;
	}

	public void setId(int envioId) {
		this.envioId = envioId;
	}

	public Cliente getCliente() {
		return cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	public Carga getCarga() {
		return carga;
	}

	public void setCarga(Carga carga) {
		this.carga = carga;
	}

	public java.util.Date getFechaRecepcion() {
		return fechaRecepcion;
	}

	public void setFechaRecepcion(java.util.Date fechaRecepcion) {
		this.fechaRecepcion = fechaRecepcion;
	}

	public java.util.Date getFechaMaximaEntrega() {
		return fechaEntregaComprometida;
	}

	public void setFechaMaximaEntrega(java.util.Date fechaMaximaEntrega) {
		this.fechaEntregaComprometida = fechaMaximaEntrega;
	}

	public List<Destinatario> getDestinatarios() {
		return destinatarios;
	}

	public void setDestinatarios(List<Destinatario> destinatarios) {
		this.destinatarios = destinatarios;
	}

	public List<ContratoConTerceros> getContratosConTerceros() {
		return contratosConTerceros;
	}

	public void setContratosConTerceros(
			List<ContratoConTerceros> contratosConTerceros) {
		this.contratosConTerceros = contratosConTerceros;
	}
	
	public Float getPrecio() {
		return precio;
	}
	
	public void setPrecio(Float precio) {
		this.precio = precio;
	}

	public Deposito getDeposito() {
		return deposito;
	}

	public void setDeposito(Deposito deposito) {
		this.deposito = deposito;
	}

	public Date getFechaEntregaComprometida() {
		return fechaEntregaComprometida;
	}

	public void setFechaEntregaComprometida(Date fechaEntregaComprometida) {
		this.fechaEntregaComprometida = fechaEntregaComprometida;
	}

	public Date getFechaLimiteDeDespacho() {
		return fechaLimiteDeDespacho;
	}

	public void setFechaLimiteDeDespacho(Date fechaLimiteDeDespacho) {
		this.fechaLimiteDeDespacho = fechaLimiteDeDespacho;
	}

	
	
	public boolean isEntregado() {
		return entregado;
	}

	public void setEntregado(boolean entregado) {
		this.entregado = entregado;
	}
	
	public int getEnvioId() {
		return envioId;
	}
	
	public void setEnvioId(int envioId) {
		this.envioId = envioId;
	}

	public boolean isEnDestino() {
		return enDestino;
	}

	public void setEnDestino(boolean enDestino) {
		this.enDestino = enDestino;
	}

	public abstract  EnvioDTO getDTO();

	public void sacarDelDeposito() {
		this.deposito = null;
	}
	
	public Date getFechaEntregaReal() {
		return fechaEntregaReal;
	}
	
	public void setFechaEntregaReal(Date fechaEntregaReal) {
		this.fechaEntregaReal = fechaEntregaReal;
	}

	public boolean isEnViaje() {
		return enViaje;
	}

	public void setEnViaje(boolean enViaje) {
		this.enViaje = enViaje;
	}

	
	
	
}
